package com.aispeech.task.lasr.event;

import com.aispeech.task.common.data.domain.Task;
import com.aispeech.task.common.exceptions.TaskException;
import com.aispeech.task.constant.LASRProgress;
import com.aispeech.task.fsm.Event;
import com.aispeech.task.lasr.LASREventType;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static com.aispeech.task.lasr.LASRTaskHandler.threadPool;
import static com.aispeech.task.lasr.LASRTaskHandler.updateTaskStatus;

@Slf4j
public class AsrEvent extends Event<Task> {
    public AsrEvent(Task task) {
        super(LASREventType.AudioCutted, task);
    }

    @Override
    public Event fire() {
        Task task = this.getTarget();

        Event nextEvent;

        try {
            updateTaskStatus(task, LASRProgress.ASR, "ts_asr");

            List<Callable<JsonNode>> tasks = new ArrayList<>();

            for (int i = 0; i < 10; i++) {
                tasks.add(new AsrTask(i, "audio_path:" + i));
            }

            List<Future<JsonNode>> futures = threadPool().invokeAll(tasks, 10, TimeUnit.MINUTES);
            List<JsonNode> asrResList = new ArrayList<>();
            futures.forEach(asrres -> {
                try {
                    asrResList.add(asrres.get());
                } catch (InterruptedException | ExecutionException e) {
                    log.error("asr err.", e);
                    asrResList.add(null);
                }
            });

            nextEvent = new FuseEvent(task, asrResList);
            updateTaskStatus(task, LASRProgress.ASRED, "ts_asred");
        } catch (InterruptedException | TaskException ex) {
            nextEvent = new ErrorEvent(task);
        }

        return nextEvent;
    }

    class AsrTask implements Callable<JsonNode> {
        private final int index;
        private final String audio;

        AsrTask(int index, String audio) {
            this.index = index;
            this.audio = audio;
        }

        @Override
        public JsonNode call() throws Exception {
            Thread.sleep(2000L);
            ObjectMapper mapper = new ObjectMapper();
            mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
//            mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);

            String rec = mapper.writeValueAsString(new HashMap() {{
                put("rec", index);
                put("audio", audio);
            }});

            return mapper.readTree(rec);
        }
    }
}
